# !/usr/bin/env python
# -*- encoding: utf-8 -*-
"""
@Desc    :   EUKOR 滚装船
"""

import copy
from typing import Union, Dict, List, Optional

from parsel import Selector
from src.enum.result import TransportModeEnum
from src.exception import WebpageLoadingErrorException, NonDataException, RebotVerificationFailureException
from src.model.ocean_bill_of_lading import OblResult, VoyageInfo
from src.plugin import OblSpiderBase
from src.util import common_util
from src.util.browser_chrome import BrowserDriver

class BillOfLadingSpider(OblSpiderBase):
    CODE = "EUKOR"

    def __init__(self,*args):
        self.key = "eukor"
        super().__init__(*args)

    def check_bill_of_lading(self, bill_of_lading):
        return bill_of_lading.startswith("EUKO") and (len(bill_of_lading) == 15 or len(bill_of_lading) == 16)

    def crawling_page(self,bill_of_lading: str, proxy=None, idx=0) -> Union[None, Dict, Selector]:
        bill_of_lading = bill_of_lading[4:]
        with BrowserDriver(proxy=proxy) as browser_driver:
            # open web
            xpath_iframe = '/html/body/main/section[2]/div/div/div/div/iframe'
            browser_driver.get("https://www.eukor.com/cargo-tracking")
            ele_iframe = browser_driver.wait_element_by_xpath(xpath_iframe)
            browser_driver.switch_to.frame(ele_iframe)
            str_input = '//*[@id="dspbno"]'
            if browser_driver.find_element_by_xpath(str_input) is None:
                raise WebpageLoadingErrorException()

            # start search
            browser_driver.find_element_by_xpath(str_input).send_keys(bill_of_lading)
            common_util.sleep_short_random()
            browser_driver.find_element_by_xpath('//*[@id="s_btn"]').click()
            common_util.sleep_short_random()
            capt_img_ele = browser_driver.wait_element_by_xpath("//div[@id='capt_img']/img")
            if capt_img_ele is not None and capt_img_ele.is_displayed():
                common_util.sleep_huge_random()
                # 等待人工解决，人工解决不了，继续机器解决
                capt_img_ele = browser_driver.wait_element_by_xpath("//div[@id='capt_img']/img")
                if capt_img_ele is not None and capt_img_ele.is_displayed():
                    raise RebotVerificationFailureException()
            # check result
            if browser_driver.find_element_by_xpath('//*[@id="data_area"]/div[2]/div/div[1]/table/tbody') is None:
                raise NonDataException()

            common_util.sleep_medium_random()
            return browser_driver.to_selector()

    def parse_ship_port_location(self, ship_port_location: str)-> (str,str,Optional[str]):
        port_date = common_util.extract_between_chars(ship_port_location, "[", "]")  # 2000/1/1
        ship_port = ship_port_location.split("[")[0].strip()
        ship_port_list = ship_port.split(",")
        port_country = ship_port_list[-1].strip()
        port_address = common_util.formatter_html_text("".join(ship_port_list[:-1]))
        port_datetime = common_util.convert_standard_datetime(port_date, "%Y/%m/%d")
        return port_address, port_country, port_datetime

    def pick_base_info(self, data:Selector) -> OblResult:
        base_info = copy.deepcopy(OblResult())
        voyage_table_row_list = data.xpath("//div[@id='data_area']/div[2]/div/div[1]/table/tbody/tr")

        for idx,row in enumerate(voyage_table_row_list):
            row_title_list = row.xpath("./th//text()").getall()
            row_title = common_util.formatter_html_text("".join(row_title_list))
            if row_title.find("[On Board]") != -1:
                orig_content = row.xpath("./td/text()").get()
                orig_address, orig_country, orig_datetime = self.parse_ship_port_location(orig_content)
                base_info.origin = orig_address
                base_info.origin_country = orig_country
            elif row_title.find("Total Unit") != -1:
                dest_content = voyage_table_row_list[idx-1].xpath("./td/text()").get()
                dest_address, dest_country, dest_datetime = self.parse_ship_port_location(dest_content)
                base_info.destination = dest_address
                base_info.destination_country = dest_country
                total_unit = row.xpath("./td/text()").get()
                if total_unit is not None:
                    base_info.container_num = int(total_unit.replace("Units","").strip())
            elif row_title.find("Current Position") != -1:
                content_list = row.xpath("./td//text()").getall()
                current_position_content = common_util.formatter_html_text("".join(content_list))
                if current_position_content.find("[Arrived]") != -1 and current_position_content.find(base_info.destination) != -1:
                    base_info.is_over = True
        return base_info

    def pick_voyage_list(self, data:Selector, base_info) -> List[VoyageInfo]:
        voyage_list: List[VoyageInfo] = []
        voyage_table_row_list = data.xpath("//div[@id='data_area']/div[2]/div/div[1]/table/tbody/tr")
        voyage_no = 0
        for idx, row in enumerate(voyage_table_row_list):
            row_title_list = row.xpath("./th//text()").getall()
            row_title = common_util.formatter_html_text("".join(row_title_list))
            if row_title.find("Vessel") != -1:
                vessel_content = row.xpath("./td/text()").get()
                vessel_content_list = vessel_content.strip().split(" ")
                voyage_number = vessel_content_list[-1]
                ship_name = " ".join(vessel_content_list[:-1]).strip()
                voyage_info = copy.deepcopy(VoyageInfo())
                voyage_no = voyage_no + 1
                voyage_info.voyage_no = voyage_no
                voyage_info.transport_mode = TransportModeEnum.SEAWAY
                voyage_info.ship_name = ship_name
                voyage_info.voyage_number= voyage_number
                voyage_list.append(voyage_info)
            elif row_title.find("Port of Loading") != -1:
                orig_content = row.xpath("./td/text()").get()
                orig_address, orig_country, orig_datetime = self.parse_ship_port_location(orig_content)
                voyage_info = voyage_list[-1]
                voyage_info.orig_port_address = orig_address
                voyage_info.orig_port_country = orig_country
                voyage_info.ship_etd = orig_datetime
            elif row_title.find("Port of Discharging") != -1 or row_title.find("Place of Delivery") != -1:
                dest_content = row.xpath("./td/text()").get()
                dest_address, dest_country, dest_datetime = self.parse_ship_port_location(dest_content)
                voyage_info = voyage_list[-1]
                voyage_info.dest_port_address = dest_address
                voyage_info.dest_port_country = dest_country
                voyage_info.ship_eta = dest_datetime

        return voyage_list

